package com.hk.webapp.interceptors;

import com.hk.webapp.utils.JwtUtil;
import com.hk.webapp.annotations.AllowAnonymous;
import com.hk.webapp.annotations.SkipPermission;
import com.hk.webapp.bean.SysAction;
import com.hk.webapp.bean.SysRoleAction;
import com.hk.webapp.bean.SysUserRole;
import com.hk.webapp.service.SysActionService;
import com.hk.webapp.service.SysRoleActionService;
import com.hk.webapp.service.SysUserRoleService;
import com.hk.webapp.utils.EHCacheUtils;
import com.hk.webapp.vo.ResultVo;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import net.sf.ehcache.CacheManager;
import org.springframework.core.annotation.Order;
import org.springframework.util.CollectionUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Slf4j
@Order(2)
public class AuthInterceptor implements HandlerInterceptor {

    @Resource
    private SysUserRoleService sysUserRoleService;
    @Resource
    SysRoleActionService sysRoleActionService;
    @Resource
    SysActionService sysActionService;
    @Resource
    private CacheManager cacheManager;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (handler instanceof HandlerMethod) {
            AllowAnonymous allClass = (((HandlerMethod) handler).getBean().getClass().getAnnotation(AllowAnonymous.class));
            AllowAnonymous allMethod = ((HandlerMethod) handler).getMethod().getAnnotation(AllowAnonymous.class);
            if (Objects.nonNull(allClass) || Objects.nonNull(allMethod)) {
                return true;
            }
            SkipPermission perClass = (((HandlerMethod) handler).getBean().getClass().getAnnotation(SkipPermission.class));
            SkipPermission perMethod = ((HandlerMethod) handler).getMethod().getAnnotation(SkipPermission.class);
            if (!Objects.isNull(perClass) || !Objects.isNull(perMethod)) {
                return true;
            }
        } else {
            return true;
        }
        Integer userId = null;
        try {
            if (request instanceof JwtUtil.CustomHttpServletRequest) {
                userId = Integer.valueOf(((JwtUtil.CustomHttpServletRequest) request).getUserId());
                if (userId == 1) {//超级管理员
                    return true;
                }
            }
            //1.0 获取请求信息
            String url = request.getRequestURI().trim().toLowerCase();
            String http_method = request.getMethod().toLowerCase();
            //获取缓存权限
            List<SysAction> cacheActions = (List<SysAction>) EHCacheUtils.getCache(cacheManager, "actions_" + userId);
            if (CollectionUtils.isEmpty(cacheActions)) {
                //2.0 获取用户角色
                List<SysUserRole> user_role_list = sysUserRoleService.getEntityListByUserId(userId);
                //3.0 获取角色权限
                List<Integer> ids = user_role_list.parallelStream().map(SysUserRole::getSysRoleId).collect(Collectors.toList());
                List<SysRoleAction> role_action_list = sysRoleActionService.getEntityListByRoleIds(ids);
                //4.0 获取所有用户权限
                List<Integer> ralIds = role_action_list.parallelStream().distinct().map(SysRoleAction::getSysActionId).collect(Collectors.toList());
                cacheActions = sysActionService.getEntityByIds(ralIds);
                EHCacheUtils.setCache(cacheManager, "actions_" + userId, cacheActions, 3600);
            }
            //5.0 判断是否有权限访问
            if (cacheActions.parallelStream().filter(c -> c.getUrl() == url && c.getHttpMethod().trim() == http_method).count() == 0) {
                //无权限
                ResultVo result = ResultVo.createByError("无访问权限");
                response.getWriter().write(JSON.toJSONString(result));
                return false;
            }
        } catch (Exception ex) {
            ResultVo result = ResultVo.createByError("非法请求");
            response.getWriter().write(JSON.toJSONString(result));
            return false;
        }

        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        log.info(request.getRequestURI());
    }
}
